package com.woniu.user.service.impl;

import com.woniu.entity.Result;
import com.woniu.user.DTO.CommentDTO;
import com.woniu.user.DTO.UserLoginDTO;
import com.woniu.user.DTO.UserRegisterDTO;
import com.woniu.user.VO.PersonalInformationVO;
import com.woniu.user.pojo.*;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.woniu.order.feign.OrderFeignClient;
import com.woniu.order.pojo.Order;
import com.woniu.user.pojo.User;
import com.woniu.user.mapper.UserMapper;
import com.woniu.user.service.IUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniu.user.util.AesUtil;
import com.woniu.user.util.SMSUtils;
import com.woniu.user.util.TencentOSS;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.Valid;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import javax.annotation.Resource;
import java.util.List;

/**
 * <p>
 * 用户端用户表 服务实现类
 * </p>
 *
 * @author LiFangyu
 * @since 2023-02-15
 */
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {


    @Autowired(required = false)
    private UserMapper userMapper;
    @Resource
    private OrderFeignClient orderFeignClient;

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public User login(@Valid UserLoginDTO userLoginDTO){
        String phone = userLoginDTO.getPhone();
        String password = userLoginDTO.getPassword();
        if (StringUtils.isEmpty(phone) || phone.length() != 11) {
            return null;
        }
        String decrypt = AesUtil.encrypt(password);
        User user = userMapper.login(phone,decrypt);
            return user;
    }



    @Override
    @Transactional //使用事务管理
    public Result register(@Valid UserRegisterDTO userRegisterDTO) {
        String name = userRegisterDTO.getName();
        String phone = userRegisterDTO.getPhone();
        String password = userRegisterDTO.getPassword();
        // 从userRegisterDTO中获取用户输入的验证码
        String inputCode = userRegisterDTO.getCode();
        if (StringUtils.isEmpty(name) || StringUtils.isEmpty(phone) || phone.length() != 11 ||StringUtils.isEmpty(password) || password.length() < 6 || StringUtils.isEmpty(inputCode)) {
            //校验不通过
            log.warn("用户注册失败，原因为：姓名，手机号，密码或验证码为空或不符合要求"); //使用warn级别
            return Result.error("姓名，手机号，密码或验证码为空或不符合要求");
        }
        // 从redis中获取该手机号对应的验证码和时间戳
        String codeKey = "code:" + phone;
        String timeKey = "time:" + phone;
        String code = (String) redisTemplate.opsForValue().get(codeKey);
        Long time = (Long) redisTemplate.opsForValue().get(timeKey);
        if (code == null || time == null) {
            // 如果redis中没有验证码或时间戳，返回一个错误信息，提示用户验证码已过期
            log.warn("用户注册失败，原因为：验证码已过期"); //使用warn级别
            return Result.error("验证码已过期，请重新发送");
        }
        if (!inputCode.equals(code)) {
            // 如果用户输入的验证码和redis中的验证码不一致，返回一个错误信息，提示用户验证码错误
            log.warn("用户注册失败，原因为：验证码错误"); //使用warn级别
            return Result.error("验证码错误，请重新输入");
        }
        if (System.currentTimeMillis() - time > 5 * 60 * 1000) {
            // 如果当前时间和redis中的时间戳相差超过5分钟，返回一个错误信息，提示用户验证码已过期
            log.warn("用户注册失败，原因为：验证码已过期"); //使用warn级别
            return Result.error("验证码已过期，请重新发送");
        }
        // 如果以上校验都通过，继续执行注册逻辑
        User userIsDeleted = userMapper.registerCheckExist(phone);
        if (userIsDeleted != null){
            //代表这个用户被逻辑删除（注销）了，但是还想重新注册
            log.warn("用户注册失败，原因为：账号已注销"); //使用warn级别
            return Result.error("账号已注销");
        }
        User registerExist = userMapper.registerExist(phone);
        if (registerExist != null){
            //用户已经存在，重复注册
            log.warn("用户注册失败，原因为：用户已存在"); //使用warn级别
            return Result.error("用户已存在");
        }
        User user = new User();
        user.setName(name);
        user.setPhone(phone);

        String encrypt = AesUtil.encrypt(password);
        try {
            user.setPassword(encrypt);
            int insert = userMapper.insert(user);
            if (insert > 0){
                //注册成功
                log.info("用户注册成功，手机号为：" + phone);
                return Result.ok(200,"注册成功");
            } else {
                //注册失败
                log.error("用户注册失败，原因为：数据库操作失败");
                return Result.error("注册失败");
            }
        } catch (Exception e) {
            //打印异常信息
            e.printStackTrace();
            //回滚事务
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            //返回未知错误
            log.error("用户注册失败，原因为：" + e.getMessage());
            return Result.error("未知错误");
        }
    }

    @Override
    public Result getVerificationCode(String phone) {
        // 检查redis中是否已经存在该手机号的验证码
        String oldCode = (String) redisTemplate.opsForValue().get("code:" + phone);
        if (oldCode != null) {
            // 返回一个错误信息，提示用户不要重复发送
            return Result.error("请不要重复发送验证码");
        }
        // 检查redis中是否已经存在该手机号的发送次数
        String countKey = "count:" + phone;
        Integer count = (Integer) redisTemplate.opsForValue().get(countKey);
        if (count == null) {
            // 如果不存在，初始化为0
            count = 0;
        }
        if (count >= 3) {
            // 如果超过了限制，返回一个错误信息，提示用户发送次数已达上限
            return Result.error("您今天的发送次数已达上限，请明天再试");
        }
        // 生成一个新的验证码
        String code = SMSUtils.generateCode();
        // 将验证码和当前时间戳一起存入redis中，设置一个过期时间，比如5分钟
        redisTemplate.opsForValue().set("code:" + phone, code, 5, TimeUnit.MINUTES);
        // 将当前时间戳存入redis中，用于计算验证码有效期
        redisTemplate.opsForValue().set("time:" + phone, System.currentTimeMillis(), 5, TimeUnit.MINUTES);
        // 将发送次数加1，并设置一个过期时间，比如24小时
        redisTemplate.opsForValue().increment(countKey);
        redisTemplate.expire(countKey, 24, TimeUnit.HOURS);
        // 将验证码发送给用户
        System.out.println(phone+"==="+code);
        SMSUtils.sendSms(phone, code);
        // 返回一个成功信息
        return Result.ok(200,"验证码已发送，请注意查收");
    }

    @Override
    public User getByUsername(String username) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("phone",username);
        User user = userMapper.selectOne(wrapper);
        return user;
    }

    @Override
    public Result getUserCircle(String phone) {
        User user = userMapper.selectByPhone(phone);
        UserCircle userCircle = userMapper.getUserCircle(user.getId());
        return Result.ok(200,"",userCircle);
    }

    @Override
    public Result getUserLikeCar(String phone) {
        User user = userMapper.selectByPhone(phone);
        List<CarParams> userLikeCar =  userMapper.getUserLikeCar(user.getId());
        return Result.ok(200,"",userLikeCar);
    }

    @Override
    public Result comment(CommentDTO commentDTO) {

        return null;
    }

    @Override
    public Result getUserCar(String phone) {
        User user = userMapper.selectByPhone(phone);
        List<UserCar> userCarList = userMapper.getUserCar(user.getId());
        return Result.ok(200,"",userCarList);
    }

    @Override
    public User getUserByPhone(String phone) {
        User user = userMapper.selectByPhone(phone);
        return user;
    }

    @Override
    public Result addPortrait(MultipartFile multipartFile,String phone) {
        String uuid = UUID.randomUUID().toString();//生成UUID
        TencentOSS.UploadIMG(multipartFile, uuid);//文件名以UUID命名
        int ok = userMapper.setPortrait(phone,uuid);
        if (ok > 0){
            return Result.ok(200);
        }
        return Result.ok(500);
    }

    @Override
    public Result personalInformation(@Valid String phone) {
        User user = userMapper.selectByPhone(phone);
        PersonalInformationVO personalInformationVO = userMapper.personalInformation(user.getId());
        personalInformationVO.setName(user.getName());
        personalInformationVO.setPortrait(user.getPortrait());
        if (personalInformationVO != null){
            return Result.ok(200,"",personalInformationVO);
        }
        return Result.error(401,"查询错误");
    }

    @Override
    public Result getAttention(@Valid String phone) {
        User user = userMapper.selectByPhone(phone);
        List<User> fans = userMapper.getAttention(user.getId());
        return Result.ok(200,"",fans);
    }

    @Override
    public Result getFans(String phone) {
        User user = userMapper.selectByPhone(phone);
        List<User> fans = userMapper.getFans(user.getId());
        return Result.ok(200,"",fans);
    }

    @Override
    public Result getCollect(String phone) {
        User user = userMapper.selectByPhone(phone);
        List<Article> userArticleCollections = userMapper.getCollect(user.getId());
        return Result.ok(200,"",userArticleCollections);
    }




    @Override
    public List<Order> getOrderInfo(String username) {
        //开启feign调用
        List<Order> orderList = orderFeignClient.selectOrderListByUsername(username).getData();
        return orderList;
    }
}
